package com.popo.android;

import java.util.ArrayList;
import java.util.Collections;
import java.util.HashSet;
import java.util.List;

import android.app.Activity;
import android.app.ListActivity;
import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ActivityInfo;
import android.content.pm.LabeledIntent;
import android.content.pm.PackageManager;
import android.content.pm.ResolveInfo;
import android.graphics.drawable.BitmapDrawable;
import android.graphics.drawable.Drawable;
import android.os.Bundle;
import android.util.Config;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.BaseAdapter;
import android.widget.ImageView;
import android.widget.ListView;
import android.widget.TextView;

public class SearchActivityByIntent extends ListActivity {
	PackageManager mPm;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		// TODO Auto-generated method stub
		super.onCreate(savedInstanceState);
		mPm=getPackageManager();
		LayoutInflater inflater = (LayoutInflater) getSystemService(Context.LAYOUT_INFLATER_SERVICE);
		ListView list = getListView();
		Intent intent = new Intent(Intent.ACTION_MAIN);
		intent.addCategory(Intent.CATEGORY_HOME);
		ResolveListAdapter resolveListAdapter = new ResolveListAdapter(this, intent, null);
		list.setAdapter(resolveListAdapter);
	}

	private final class DisplayResolveInfo {
		ResolveInfo ri;
		CharSequence displayLabel;
		Drawable displayIcon;
		CharSequence extendedInfo;
		Intent origIntent;

		DisplayResolveInfo(ResolveInfo pri, CharSequence pLabel,
				CharSequence pInfo, Intent pOrigIntent) {
			ri = pri;
			displayLabel = pLabel;
			extendedInfo = pInfo;
			origIntent = pOrigIntent;
		}
	}

	private final class ResolveListAdapter extends BaseAdapter {
		private final Intent mIntent;
		private final LayoutInflater mInflater;

		private List<DisplayResolveInfo> mList;

		public ResolveListAdapter(Context context, Intent intent,
				Intent[] initialIntents) {
			mIntent = new Intent(intent);
			mIntent.setComponent(null);
			mInflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);

			List<ResolveInfo> rList = mPm
					.queryIntentActivities(
							intent,
							PackageManager.MATCH_DEFAULT_ONLY
									|  PackageManager.GET_RESOLVED_FILTER);
			int N;
			if ((rList != null) && ((N = rList.size()) > 0)) {
				// Only display the first matches that are either of equal
				// priority or have asked to be default options.
				ResolveInfo r0 = rList.get(0);
				for (int i = 1; i < N; i++) {
					ResolveInfo ri = rList.get(i);
					if (Config.LOGV)
						Log.v("ResolveListActivity", r0.activityInfo.name + "="
								+ r0.priority + "/" + r0.isDefault + " vs "
								+ ri.activityInfo.name + "=" + ri.priority
								+ "/" + ri.isDefault);
					if (r0.priority != ri.priority
							|| r0.isDefault != ri.isDefault) {
						while (i < N) {
							rList.remove(i);
							N--;
						}
					}
				}
				if (N > 1) {
					ResolveInfo.DisplayNameComparator rComparator = new ResolveInfo.DisplayNameComparator(
							mPm);
					Collections.sort(rList, rComparator);
				}

				mList = new ArrayList<DisplayResolveInfo>();

				// First put the initial items at the top.
				if (initialIntents != null) {
					for (int i = 0; i < initialIntents.length; i++) {
						Intent ii = initialIntents[i];
						if (ii == null) {
							continue;
						}
						ActivityInfo ai = ii.resolveActivityInfo(
								getPackageManager(), 0);
						if (ai == null) {
							Log.w("ResolverActivity", "No activity found for "
									+ ii);
							continue;
						}
						ResolveInfo ri = new ResolveInfo();
						ri.activityInfo = ai;
						if (ii instanceof LabeledIntent) {
							LabeledIntent li = (LabeledIntent) ii;
							ri.resolvePackageName = li.getSourcePackage();
							ri.labelRes = li.getLabelResource();
							ri.nonLocalizedLabel = li.getNonLocalizedLabel();
							ri.icon = li.getIconResource();
						}
						mList.add(new DisplayResolveInfo(ri, ri
								.loadLabel(getPackageManager()), null, ii));
					}
				}

				// Check for applications with same name and use application
				// name or
				// package name if necessary
				r0 = rList.get(0);
				int start = 0;
				CharSequence r0Label = r0.loadLabel(mPm);
				for (int i = 1; i < N; i++) {
					if (r0Label == null) {
						r0Label = r0.activityInfo.packageName;
					}
					ResolveInfo ri = rList.get(i);
					CharSequence riLabel = ri.loadLabel(mPm);
					if (riLabel == null) {
						riLabel = ri.activityInfo.packageName;
					}
					if (riLabel.equals(r0Label)) {
						continue;
					}
					processGroup(rList, start, (i - 1), r0, r0Label);
					r0 = ri;
					r0Label = riLabel;
					start = i;
				}
				// Process last group
				processGroup(rList, start, (N - 1), r0, r0Label);
			}
		}

		private void processGroup(List<ResolveInfo> rList, int start, int end,
				ResolveInfo ro, CharSequence roLabel) {
			// Process labels from start to i
			int num = end - start + 1;
			if (num == 1) {
				// No duplicate labels. Use label for entry at start
				mList.add(new DisplayResolveInfo(ro, roLabel, null, null));
			} else {
				boolean usePkg = false;
				CharSequence startApp = ro.activityInfo.applicationInfo
						.loadLabel(mPm);
				if (startApp == null) {
					usePkg = true;
				}
				if (!usePkg) {
					// Use HashSet to track duplicates
					HashSet<CharSequence> duplicates = new HashSet<CharSequence>();
					duplicates.add(startApp);
					for (int j = start + 1; j <= end; j++) {
						ResolveInfo jRi = rList.get(j);
						CharSequence jApp = jRi.activityInfo.applicationInfo
								.loadLabel(mPm);
						if ((jApp == null) || (duplicates.contains(jApp))) {
							usePkg = true;
							break;
						} else {
							duplicates.add(jApp);
						}
					}
					// Clear HashSet for later use
					duplicates.clear();
				}
				for (int k = start; k <= end; k++) {
					ResolveInfo add = rList.get(k);
					if (usePkg) {
						// Use application name for all entries from start to
						// end-1
						mList.add(new DisplayResolveInfo(add, roLabel,
								add.activityInfo.packageName, null));
					} else {
						// Use package name for all entries from start to end-1
						mList.add(new DisplayResolveInfo(
								add,
								roLabel,
								add.activityInfo.applicationInfo.loadLabel(mPm),
								null));
					}
				}
			}
		}

		public ResolveInfo resolveInfoForPosition(int position) {
			if (mList == null) {
				return null;
			}

			return mList.get(position).ri;
		}

		public Intent intentForPosition(int position) {
			if (mList == null) {
				return null;
			}

			DisplayResolveInfo dri = mList.get(position);

			Intent intent = new Intent(dri.origIntent != null ? dri.origIntent
					: mIntent);
			intent.addFlags(Intent.FLAG_ACTIVITY_FORWARD_RESULT
					| Intent.FLAG_ACTIVITY_PREVIOUS_IS_TOP);
			ActivityInfo ai = dri.ri.activityInfo;
			intent.setComponent(new ComponentName(
					ai.applicationInfo.packageName, ai.name));
			return intent;
		}

		public int getCount() {
			return mList != null ? mList.size() : 0;
		}

		public Object getItem(int position) {
			return position;
		}

		public long getItemId(int position) {
			return position;
		}

		public View getView(int position, View convertView, ViewGroup parent) {
			View view;
			if (convertView == null) {
				view = mInflater.inflate(R.layout.resolve_list_item, parent,
						false);
			} else {
				view = convertView;
			}
			bindView(view, mList.get(position));
			return view;
		}

		private final void bindView(View view, DisplayResolveInfo info) {
			TextView text = (TextView) view.findViewById(android.R.id.text1);
			TextView text2 = (TextView) view.findViewById(android.R.id.text2);
			ImageView icon = (ImageView) view.findViewById(R.id.icon);
			text.setText(info.displayLabel);
			if (info.extendedInfo != null) {
				text2.setVisibility(View.VISIBLE);
				text2.setText(info.extendedInfo);
			} else {
				text2.setVisibility(View.GONE);
			}
			if (info.displayIcon == null) {
				info.displayIcon = info.ri.loadIcon(mPm);
			}
			icon.setImageDrawable(info.displayIcon);
		}
	}

}
